package com.xhwl.logistics.service.cent.server;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.common.dto.cent.vehicle.feign.VehicleIntervalStatisticsQuery;
import com.xhwl.common.dto.cent.vehicle.feign.VehicleParkingLotQuery;
import com.xhwl.common.enums.vehicle.InOutEnum;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.vo.cent.vehicle.bi.VehicleAccessRecordIntervalStatisticsVO;
import com.xhwl.common.vo.cent.vehicle.bi.VehicleStatisticsVO;
import com.xhwl.logistics.bo.VehicleParkingLotSecondBO;
import com.xhwl.logistics.bo.cent.VehicleIntegratedConfigBO;
import com.xhwl.logistics.converter.ToPage;
import com.xhwl.logistics.dto.http.CarDispatchMapDTO;
import com.xhwl.logistics.dto.http.CarportDaHuaKeTopGeoIOCDTO;
import com.xhwl.logistics.dto.http.CarportFreeKeTopGeoDTO;
import com.xhwl.logistics.dto.http.ParkingLotAreaInfoDaHuaDTO;
import com.xhwl.logistics.entity.VehicleAccessRecord;
import com.xhwl.logistics.entity.VehicleArea;
import com.xhwl.logistics.service.cent.IBIVehicleService;
import com.xhwl.logistics.service.cent.QueryDeviceService;
import com.xhwl.logistics.service.impl.VehicleAccessRecordServiceImpl;
import com.xhwl.logistics.service.impl.VehicleAreaServiceImpl;
import com.xhwl.logistics.service.impl.VehicleParkingLotServiceImpl;
import com.xhwl.logistics.service.impl.http.CarDispatchHttpServiceImpl;
import com.xhwl.logistics.service.impl.http.DaHuaHttpServiceImpl;
import com.xhwl.logistics.service.impl.http.KeTopGeoHttpServiceImpl;
import com.xhwl.logistics.util.AboutDateUtil;
import com.xhwl.logistics.util.MathUtil;
import com.xhwl.logistics.util.RedisUtils;
import com.xhwl.logistics.vo.VehicleAccessRecordSecondVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 大华和科拓iod接口的具体实现类
 */
@Slf4j
//@Service
public class VehicleDaHuaAndKeTopGeoIOCServiceImpl implements IVehicleDaHuaAndKeTopGeoIOCService {

    @Autowired
    private KeTopGeoHttpServiceImpl keTopGeoHttpService;

    @Autowired
    private DaHuaHttpServiceImpl daHuaHttpService;

    @Autowired
    private CarDispatchHttpServiceImpl carDispatchHttpService;

    @Autowired
    private VehicleParkingLotServiceImpl vehicleParkingLotService;

    @Autowired
    private VehicleAreaServiceImpl vehicleAreaService;

    @Autowired
    private VehicleAccessRecordServiceImpl vehicleAccessRecordService;

    @Autowired
    private IBIVehicleService ibiVehicleService;

    @Autowired
    private QueryDeviceService queryDeviceService;

    @Autowired
    private ToPage toPage;

    @Autowired
    private RedisUtils redisUtils;

    /**
     * 空置率是否需要%的布尔值，当前为需要加上%
     */
    private static final Boolean needSign = true;
    private static final long zeroLong = 0;
    private static final String officeArea = "0";
    private static final String truckArea = "1";
    private static final String otherArea = "-1";
    private static final String vehicleRedis = "logistics-mengniu-dahua";

    /**
     * 获取大华和科拓地磁感应的车位信息的实现类
     */
    @Override
    public ResultJson getDaHuaAndKeTopGeoCarportInfo(VehicleParkingLotQuery vehicleParkingLotQuery) {
        if(vehicleParkingLotQuery.getProjectId()==null){
            throw new BusinessException("项目id不能为空！");
        }
        VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(vehicleParkingLotQuery.getProjectId());

        //获取科拓地磁感应的车位信息，并将其封装到CarportDaHuaKeTopGeoIOCDTO类中
        List<CarportFreeKeTopGeoDTO> keTopGeoFreeCarspot = keTopGeoHttpService.getKeTopGeoFreeCarspot(vehicleIntegratedConfigBO);
        CarportDaHuaKeTopGeoIOCDTO carportDaHuaKeTopGeoIOCDTO = setKeTopGeoCarportInfo(keTopGeoFreeCarspot, new CarportDaHuaKeTopGeoIOCDTO());
        //根据科拓地磁感应的车位信息求出车位的空置率
        carportDaHuaKeTopGeoIOCDTO.setRateKeTopGeo(
                MathUtil.getRateFromInterger(carportDaHuaKeTopGeoIOCDTO.getTotalKeTopGeo(),carportDaHuaKeTopGeoIOCDTO.getFreeKeTopGeo(),needSign)
        );

        //根据集成配置中的remark字段获取大华车场车位信息，并将其封装到CarportDaHuaKeTopGeoIOCDTO类中
        List<VehicleArea> vehicleAreaList = vehicleAreaService.list(conditionForAreaFromRemark(vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemark()));
        if(vehicleAreaList.size() > 1){
            throw new BusinessException("通过该区域备注找到多个区域信息！");
        }else if(vehicleAreaList.size() == 0){
            throw new BusinessException("通过该区域备注未找到区域信息！");
        }
        VehicleArea vehicleArea = vehicleAreaList.get(0);
        List<ParkingLotAreaInfoDaHuaDTO> parkingLotAreaInfo = daHuaHttpService.getParkingLotAreaInfo(vehicleIntegratedConfigBO);
        ParkingLotAreaInfoDaHuaDTO parkingLotAreaInfoDaHuaDTO = parkingLotAreaInfo.stream().filter(s -> {
            if (StringUtils.equals(s.getId(), vehicleArea.getThirdAreaId())) {
                return true;
            } else {
                return false;
            }
        }).findAny().orElse(null);
        if(parkingLotAreaInfoDaHuaDTO==null){
            throw new BusinessException("大华将该区域删除，请同步最新区域！");
        }
        carportDaHuaKeTopGeoIOCDTO.setTotalDaHua(parkingLotAreaInfoDaHuaDTO.getTotalLot());
        carportDaHuaKeTopGeoIOCDTO.setFreeDaHua(parkingLotAreaInfoDaHuaDTO.getIdleLot());
        //根据大华的车位信息求出车位的空置率
        carportDaHuaKeTopGeoIOCDTO.setRateDaHua(
                MathUtil.getRateFromInterger(carportDaHuaKeTopGeoIOCDTO.getTotalDaHua(),carportDaHuaKeTopGeoIOCDTO.getFreeDaHua(),needSign)
        );

        //根据出行记录算出办公区平均停车时长
        Date endTime = new Date();
        Date startTime = AboutDateUtil.theSameDayOfDate(endTime);
        List<VehicleAccessRecord> vehicleAccessRecordListFromDaHua = vehicleAccessRecordService.list(conditionForAccessRecordFromToday(
                vehicleIntegratedConfigBO.getVehicleSystemInfoBO().getProjectId()
                ,vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemark(), startTime, endTime
        ));
        List<Long> averTimeListFromDaHua = vehicleAccessRecordListFromDaHua.stream().map(s -> {
            if (s.getExitTime() == null) {
                return new Date().getTime() - s.getEnterTime().getTime();
            }else if (s.getEnterTime() == null){
                return zeroLong;
            }else {
                return s.getExitTime().getTime() - s.getEnterTime().getTime();
            }
        }).collect(Collectors.toList());
        carportDaHuaKeTopGeoIOCDTO.setParkingTimeDaHua(MathUtil.getTimeByLong(averTimeListFromDaHua));

        //根据出行记录算出办公区平均停车时长
        List<VehicleAccessRecord> vehicleAccessRecordListFromKeTopGeo = vehicleAccessRecordService.list(conditionForAccessRecordFromToday(
                vehicleIntegratedConfigBO.getVehicleSystemInfoBO().getProjectId()
                ,vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemarkUnion(), startTime, endTime
        ));
        List<Long> averTimeListFromKeTopGeo = vehicleAccessRecordListFromKeTopGeo.stream().map(s -> {
            if (s.getExitTime() == null) {
                return new Date().getTime() - s.getEnterTime().getTime();
            }else if (s.getEnterTime() == null){
                return zeroLong;
            }else {
                return s.getExitTime().getTime() - s.getEnterTime().getTime();
            }
        }).collect(Collectors.toList());
        carportDaHuaKeTopGeoIOCDTO.setParkingTimeKeTopGeo(MathUtil.getTimeByLong(averTimeListFromKeTopGeo));
        return ResultJson.successWithResult(carportDaHuaKeTopGeoIOCDTO);
    }

    /**
     * 获取大华各个区域的车辆进出统计的趋势的实现类
     */
    @Override
    public ResultJson getDaHuaAndKeTopGeoAccessRecordTrend(VehicleIntervalStatisticsQuery vehicleIntervalStatisticsQuery) {
        VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(vehicleIntervalStatisticsQuery.getProjectId());
        VehicleParkingLotSecondBO vehicleParkingLotSecondBO = vehicleParkingLotService.queryParkingLot(vehicleIntervalStatisticsQuery.getProjectId(), null);
        List<VehicleArea> vehicleAreaList = vehicleAreaService.list(conditionForAreaFromParkingLotId(vehicleParkingLotSecondBO.getId()));
        List<VehicleStatisticsVO<List<VehicleAccessRecordIntervalStatisticsVO>>> vehicleStatisticsVOS = new LinkedList<>();
        String remark = vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemark();
        String remarkUnion = vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemarkUnion();
        //由于一个车场的区域比较少
        for (VehicleArea vehicleArea : vehicleAreaList) {
            vehicleIntervalStatisticsQuery.setParkingLotName(vehicleArea.getRemark());
            VehicleStatisticsVO<List<VehicleAccessRecordIntervalStatisticsVO>> listVehicleStatisticsVO = ibiVehicleService.accessRecordIntervalStatistics(vehicleIntervalStatisticsQuery);
            if(StringUtils.equals(remark, vehicleArea.getRemark())){
                listVehicleStatisticsVO.setParkingLotName(officeArea);
            }else if(StringUtils.equals(remarkUnion, vehicleArea.getRemark())){
                listVehicleStatisticsVO.setParkingLotName(truckArea);
            }else{
                listVehicleStatisticsVO.setParkingLotName(otherArea);
            }
            vehicleStatisticsVOS.add(listVehicleStatisticsVO);
        }
        return ResultJson.successWithResult(vehicleStatisticsVOS);
    }

    /**
     * 获取最新的大华货车区进出记录的实现类
     */
    @Override
    public ResultJson getDaHuaAndKeTopGeoAccessRecordRecently(VehicleParkingLotQuery vehicleParkingLotQuery) {
        VehicleIntegratedConfigBO vehicleIntegratedConfigBO = queryDeviceService.queryIntegratedConfigFromProjectId(vehicleParkingLotQuery.getProjectId());
        Page<VehicleAccessRecord> vehicleAccessRecordPage = new Page<>(vehicleParkingLotQuery.getPageNumber(), vehicleParkingLotQuery.getPageSize());
        Page<VehicleAccessRecord> page = vehicleAccessRecordService.page(
                vehicleAccessRecordPage, conditionForAccessRecordRealtimeFromProjectId(vehicleParkingLotQuery.getProjectId(), vehicleIntegratedConfigBO.getVehicleParkingInfoBO().getRemarkUnion()));

        List<String> collect = page.getRecords().stream().map(VehicleAccessRecord::getPlateNumber).collect(Collectors.toList());
        //去重
        List<String> plateNumbers = new LinkedList<>();
        for (String plateNumber : collect) {
            String plate = plateNumbers.stream().filter(s -> {
                if (StringUtils.equals(s, plateNumber)) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if(plate == null){
                plateNumbers.add(plateNumber);
            }
        }

        List<CarDispatchMapDTO> carTypeByCarNum = carDispatchHttpService.getCarTypeByCarNum(vehicleIntegratedConfigBO, plateNumbers);


        //由于车辆调度方暂未给予接口来判断车辆的车辆类型，故暂使用以下方式。
        List<VehicleAccessRecordSecondVO> vehicleAccessRecordSecondVOList = page.getRecords().stream().map(vehicleAccessRecord->{
            return this.assemAccessRecordAndThird(vehicleAccessRecord, carTypeByCarNum);
        }).collect(Collectors.toList());
        return ResultJson.successWithResult(toPage.toPage(page, vehicleAccessRecordSecondVOList));
    }



    /**
     * 将出行记录和车辆调度中的信息组装成VehicleAccessRecordSecondVO类
     */
    private VehicleAccessRecordSecondVO assemAccessRecordAndThird(VehicleAccessRecord vehicleAccessRecord, List<CarDispatchMapDTO> carDispatchMapDTOS){
        VehicleAccessRecordSecondVO vehicleAccessRecordSecondVO = new VehicleAccessRecordSecondVO();
        if(vehicleAccessRecord!=null){
            vehicleAccessRecordSecondVO.setPlateNumber(vehicleAccessRecord.getPlateNumber());
            if (vehicleAccessRecord.getStatus()==0){
                vehicleAccessRecordSecondVO.setPassageName(vehicleAccessRecord.getEnterPassageName());
                vehicleAccessRecordSecondVO.setStatus(InOutEnum.IN.getDisplay());
                vehicleAccessRecordSecondVO.setInOutTime(vehicleAccessRecord.getEnterTime());
                vehicleAccessRecordSecondVO.setImgUrl(vehicleAccessRecord.getEnterPictureUrl());
            }else{
                vehicleAccessRecordSecondVO.setPassageName(vehicleAccessRecord.getExitPassageName());
                vehicleAccessRecordSecondVO.setStatus(InOutEnum.OUT.getDisplay());
                vehicleAccessRecordSecondVO.setInOutTime(vehicleAccessRecord.getExitTime());
                vehicleAccessRecordSecondVO.setImgUrl(vehicleAccessRecord.getExitPictureUrl());
            }
            CarDispatchMapDTO carDispatchMapDTO1 = carDispatchMapDTOS.stream().filter(carDispatchMapDTO -> {
                if (StringUtils.equals(carDispatchMapDTO.getKey(), vehicleAccessRecord.getPlateNumber())) {
                    return true;
                } else {
                    return false;
                }
            }).findAny().orElse(null);
            if (carDispatchMapDTO1 != null){
                vehicleAccessRecordSecondVO.setCardType(carDispatchMapDTO1.getValue());
            }else{
                vehicleAccessRecordSecondVO.setCardType("非货车");
            }
        }
        return vehicleAccessRecordSecondVO;
    }

    /**
     * 将科拓地磁感应的车位信息转换为大华和科拓地磁感应IOC的车位信息
     */
    private CarportDaHuaKeTopGeoIOCDTO setKeTopGeoCarportInfo(
            List<CarportFreeKeTopGeoDTO> carportFreeKeTopGeoDTOList,
            CarportDaHuaKeTopGeoIOCDTO carportDaHuaKeTopGeoIOCDTO){
        //计算科拓地磁感应的总车位数
        List<Integer> totalsFromKeTopGeo = carportFreeKeTopGeoDTOList.stream().map(s -> Integer.valueOf(s.getTotalSpaceNum())).collect(Collectors.toList());
        Integer totalKeTopGeo = totalsFromKeTopGeo.stream().reduce(carportDaHuaKeTopGeoIOCDTO.getTotalKeTopGeo(), (it, value) -> { return it = it + value; });

        //计算科拓地磁感应的剩余车位数
        List<Integer> freesFromKeTopGeo = carportFreeKeTopGeoDTOList.stream().map(s -> Integer.valueOf(s.getFreeSpaceNum())).collect(Collectors.toList());
        Integer freeKeTopGeo = freesFromKeTopGeo.stream().reduce(carportDaHuaKeTopGeoIOCDTO.getFreeKeTopGeo(), (it, value) -> {
            return it = it + value;
        });

        carportDaHuaKeTopGeoIOCDTO.setTotalKeTopGeo(totalKeTopGeo);
        carportDaHuaKeTopGeoIOCDTO.setFreeKeTopGeo(freeKeTopGeo);
        return carportDaHuaKeTopGeoIOCDTO;
    }

    /**
     * 构建通过备注信息获取区域信息的条件
     */
    private Wrapper<VehicleArea> conditionForAreaFromRemark(String remark){
        return new LambdaQueryWrapper<VehicleArea>().eq(
                VehicleArea::getRemark,remark
        );
    }

    /**
     * 构建获取今日的所有出行记录的条件
     */
    private Wrapper<VehicleAccessRecord> conditionForAccessRecordFromToday(Integer projectId, String remark, Date startTime, Date endTime){
        return new LambdaQueryWrapper<VehicleAccessRecord>().eq(
                VehicleAccessRecord::getProjectId,projectId
        ).eq(
                Objects.nonNull(remark), VehicleAccessRecord::getParkId, remark
        ).between(
                VehicleAccessRecord::getEnterTime,startTime,endTime
        );
    }

    /**
     * 通过车场id查询该车场下的所有区域信息
     */
    private Wrapper<VehicleArea> conditionForAreaFromParkingLotId(Integer parkingLotId){
        return new LambdaQueryWrapper<VehicleArea>().eq(
                VehicleArea::getParkingLotId,parkingLotId
        );
    }

    /**
     * 根据项目id查询最新的进记录或出记录
     */
    private Wrapper<VehicleAccessRecord> conditionForAccessRecordRealtimeFromProjectId(Integer projectId, String remarkUnion){
        return new LambdaQueryWrapper<VehicleAccessRecord>().eq(
                VehicleAccessRecord::getProjectId, projectId
        ).eq(VehicleAccessRecord::getParkId, remarkUnion)
                .orderByDesc(VehicleAccessRecord::getUpdatedAt);
    }
}
